#!/usr/bin/env python
# -*- coding: utf-8 -*-

#    Copyright © 2011 Jaume Delclòs Coll (cosarara97)

#    This file is part of pyFSF.

#    pyFSF is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    pyFSF is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with pyFSF.  If not, see <http://www.gnu.org/licenses/>.


import sys  # , os
#import binascii
from romHacking import *

 # Import Qt modules
from PyQt4 import QtCore, QtGui

 # Import the compiled UI module
from window import Ui_MainWindow


class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.connect(self.ui.search_button, QtCore.SIGNAL('clicked()'),
                     self.search)
        self.connect(self.ui.next_button, QtCore.SIGNAL('clicked()'),
                     self.next)
        self.connect(self.ui.actionOpen, QtCore.SIGNAL('triggered()'),
                     self.openROM)
        self.connect(self.ui.actionQuit, QtCore.SIGNAL('triggered()'),
                     self.dw)

        self.connect(self.ui.lineEdit_length,
                     QtCore.SIGNAL('textChanged(QString)'),
                     self.disable_next)
        self.connect(self.ui.lineEdit_offset,
                     QtCore.SIGNAL('textChanged(QString)'),
                     self.disable_next)

        self.connect(self.ui.radio_Hex, QtCore.SIGNAL('clicked()'),
                     self.disable_next)
        self.connect(self.ui.radio_Dec, QtCore.SIGNAL('clicked()'),
                     self.disable_next)

        self.connect(self.ui.checkBox_margin, QtCore.SIGNAL('clicked()'),
                     self.toggle_margin)

        self.connect(self.ui.rep_button, QtCore.SIGNAL('clicked()'),
                     self.repoint)

        self.connect(self.ui.conv_button, QtCore.SIGNAL('clicked()'),
                     self.convert)
                     
        self.connect(self.ui.actionAbout, QtCore.SIGNAL('triggered()'),
                     self.about)

        self.fileName = None
        self.hexmode = False
        self.next_num = 1
        self.usingMargin = False

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////----Disable-next----///////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////
    def disable_next(self):
        self.ui.next_button.setEnabled(False)

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////-----CHECK-MODE-----///////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def check_mode(self):
        if self.ui.radio_Hex.isChecked():
            self.hexmode = True
        else:
            self.hexmode = False

 #//////////////////////////////------//////////////////////////////////////////
 #/////////////////////////-----SEARCH-----/////////////////////////////////////
 #//////////////////////////////------//////////////////////////////////////////

    def search(self):
        self.check_mode()
 #--------------------This checks if user has opened a ROM----------------------
        if not self.fileName:
            print "Error: No input file"
            self.ui.found_label.setText("No input file")
            return
 #------------------------------------------------------------------------------
 #------------------This checks the program mode (hex or dec)-------------------
        if self.hexmode:
            if self.ui.lineEdit_length.text():
                self.length = conv_hex2dec(self.ui.lineEdit_length.text())
            else:
                print "Error: length not specified"
                self.ui.found_label.setText("length not specified")
                return
        else:
            if self.ui.lineEdit_length.text():
                try:
                    self.length = int(self.ui.lineEdit_length.text())
                except:
                    print "Error: length is NaN"
                    self.ui.found_label.setText("length is NaN")
                    return
            else:
                print "Error: length not specified"
                self.ui.found_label.setText("length not specified")
                return
 #------------------------------------------------------------------------------

        self.start = str(self.ui.lineEdit_offset.text())

 #--------------------This checks if there is length ---------------------------
        if not self.length:
            print "Error: length not specified"
            self.ui.found_label.setText("length not specified")
            return

 #------------------------------------------------------------------------------

 #--------------------This checks if there is start ----------------------------
        if not self.start:  # If user hasn't introduced a start
            self.start = 0  # Start will be 0
        self.fcontents2 = convn_h2a(self.fcontents)
 #------------------------------------------------------------------------------

 #--------------------This checks if specified length is too long =P------------
        total_rom_length = len(self.fcontents2) / 2
        if total_rom_length < self.length:
            print "Error: length is too long"
            self.ui.found_label.setText("length is too long")
            return
 #------------------------------------------------------------------------------

        if self.usingMargin:
            # Are we in hexadecmial mode?
            if self.hexmode:
                # If we are, we have to tell int()
                try:
                    margin = int(str(self.ui.lineEdit_margin.text()), 16)
                    print "margin = " + str(margin)
                except:
                    print "Margin ERROR: You should enter a number."
                    print "It'll be in hex or dec dependinding of that radio"
                    print "button."
                    self.ui.found_label.setText("Margin Error")
                    return
            else:
                try:
                    # If we aren't we are in decimal, so int will use base 10
                    margin = int(str(self.ui.lineEdit_margin.text()))
                    print "margin = " + str(margin)
                except:
                    print "Margin ERROR: You should enter a number."
                    print "It'll be in hex or dec dependinding of that radio"
                    print "button."
                    self.ui.found_label.setText("Margin Error")
                    return

        else:
            margin = 0
#        Ok, so now if the user has enabled margin it'll be as an int
#        in the local margin variable.

#-------------------This searches the free space--------------
        self.offset_found = self.buscar("ff", self.length + margin,
                                        conv_hex2dec(self.start) * 2)
        if self.offset_found == -1:
            print "Error: Not found"
            self.ui.found_label.setText("Not found")
            return
        else:
            self.offset_found_str = str(conv_dec2hex(self.offset_found + margin))
            self.ui.next_button.setEnabled(True)

        print "Space with " + str(self.length)\
            + " FF's in offset " + self.offset_found_str
        self.ui.found_label.setText("offset: 0x" + self.offset_found_str)

        self.next_num = 1

 #////////////////////////////----------////////////////////////////////////////
 #//////////////////////////-----NEXT-----//////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def next(self):
        # TODO:
        # Next needs to apply margin
        self.check_mode()
 #--------------------This checks if user has opened a ROM----------------------
        if not self.fileName:
            print "Error: No input file"
            self.ui.found_label.setText("No input file")
            return
 #------------------------------------------------------------------------------
 
        if self.usingMargin:
            # Are we in hexadecmial mode?
            if self.hexmode:
                # If we are, we have to tell int()
                try:
                    margin = int(str(self.ui.lineEdit_margin.text()), 16)
                    print "margin = " + str(margin)
                except:
                    print "Margin ERROR: You should enter a number."
                    print "It'll be in hex or dec dependinding of that radio"
                    print "button."
                    self.ui.found_label.setText("Margin Error")
                    return
            else:
                try:
                    # If we aren't we are in decimal, so int will use base 10
                    margin = int(str(self.ui.lineEdit_margin.text()))
                    print "margin = " + str(margin)
                except:
                    print "Margin ERROR: You should enter a number."
                    print "It'll be in hex or dec dependinding of that radio"
                    print "button."
                    self.ui.found_label.setText("Margin Error")
                    return
        else:
            margin = 0

        start_next = conv_hex2dec(self.start) + self.length * self.next_num
        print conv_dec2hex(start_next)

        self.offset_found = self.buscar("ff", self.length,
                                        start_next * 2)
        self.offset_found += margin
        self.next_num += 1
        if self.offset_found == -1:
            print "Error: Not found"
            self.ui.found_label.setText("Not found")
            return
        else:
            self.offset_found_str = conv_dec2hex(self.offset_found)
            #self.next_length = self.length
            #self.ui.next_button.setEnabled(True)
        print "Space with " + str(self.length)\
            + " FF's in offset " + self.offset_found_str
        self.ui.found_label.setText("offset: 0x" + self.offset_found_str)

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////////-----DW-----///////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def dw(self):
        quit()

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////////--OPEN-ROM--///////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def openROM(self):
        self.fileName = QtGui.QFileDialog.getOpenFileName(self, "Open ROM", "~",
                                               "GBA ROM (*.gba);;All Files (*)")
        if self.fileName == "":
            return
        print self.fileName
        f = open(self.fileName, "rb")
        self.fcontents = f.read()
        f.close()

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////////---BUSCAR---///////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def buscar(self, byte, length, start):
        sub = byte * length  # Sub = byte a buscar (ff) * longitud a buscar
        offset_found = self.fcontents2.find(sub, start) / 2
        return offset_found

 #//////////////////////////////////////////////////////////////////////////////
    def toggle_margin(self):
        if self.ui.checkBox_margin.isChecked():
            self.ui.lineEdit_margin.setEnabled(True)
            self.usingMargin = True
        else:
            self.ui.lineEdit_margin.setEnabled(False)
            self.usingMargin = False

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////////---REPOINT---//////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def repoint(self):
        offset = str(self.ui.lineEdit_rep.text())
        if len(offset) != 6:
            print "Error: offset must be 6 characters"
            return
        offset2 = offset[4:6] + offset[2:4] + offset[0:2]
        print offset2
        self.ui.lineEdit_rep.setText(offset2)

 #////////////////////////////----------////////////////////////////////////////
 #///////////////////////////---CONVERT---//////////////////////////////////////
 #////////////////////////////----------////////////////////////////////////////

    def convert(self):
        numberToConvert = str(self.ui.lineEdit_conv.text())
        if numberToConvert == "":
            print "lol"
            return
        if numberToConvert[:2] == "0x":
            #  Introduced number is in Hex
            convertedNumber = conv_hex2dec(numberToConvert)
            print numberToConvert + " in dec = " + str(convertedNumber)
            self.ui.lineEdit_conv.setText(str(convertedNumber))
        else:
            #  Introduced number is in Dec
            convertedNumber = conv_dec2hex(int(numberToConvert))
            print numberToConvert + " in hex = 0x" + str(convertedNumber)
            self.ui.lineEdit_conv.setText("0x" + str(convertedNumber))
            
    def about(self):
        QtGui.QMessageBox.about(self,
                                "About pyFSF",
                                "pyFSF v1.99 \
                                \nby: Jaume Delclos (cosarara97)\
                                \nRead the README for more info.")


def main():
    app = QtGui.QApplication(sys.argv)
    window123 = Main()
    window123.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
